//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.IO.Packaging;
using System.Reflection;
using System.Windows.Markup;
using OpenLS.Chart.Serialization;
using OpenLS.Core.Notification;
using OpenLS.Core.Serialization;
using OpenLS.Drawing;
using OpenLS.Drawing.Serialization;

namespace OpenLS.Chart
{
    [ContentProperty("PlotArea")]
    public class ChartArea : ViewModelBase, IOfficeXmlSerializable, IShape
    {
        private readonly List<PivotFormat> _pivotFormats = new List<PivotFormat>();
        private readonly List<DrawingAnchor> _userShapes = new List<DrawingAnchor>();
        private bool _autoTitleDeleted;
        private Surface _backWall;
        private ChartStyle _chartStyle = new ChartStyle();
        private ColorMapping _clrMapOvr;
        private bool _date1904;
        private DisplayBlanksAs _dispBlanksAs;
        private ExtensionElement _extension;
        private Surface _floor;
        private string _lang;
        private Legend _legend;
        private PivotSource _pivotSource;
        private PlotArea _plotArea;
        private bool _plotVisOnly;
        private PrintSettings _printSettings;
        private Protection _protection;
        private bool _roundedCorners;
        private bool _showDLblsOverMax;
        private Surface _sideWall;
        private ShapeProperties _spPr;
        private Theme _theme;

        public ChartArea()
        {
            
        }
        private Title _title;
        private TextBody _txPr;
        private View3D _view3D;
        private ExternalData externalData;

        public Theme Theme
        {
            get { return _theme; }
            set
            {
                _theme = value;
                notifyPropertyChanged("Theme");
            }
        }

        public Title Title
        {
            get { return _title; }
            set
            {
                _title = value;
                notifyPropertyChanged("Title");
            }
        }

        public bool Date1904
        {
            get { return _date1904; }
            set { _date1904 = value; }
        }

        public PrintSettings PrintSettings
        {
            get { return _printSettings; }
            set
            {
                _printSettings = value;
                notifyPropertyChanged("PrintSettings");
            }
        }


        public TextBody TextProperties
        {
            get { return _txPr; }
            set
            {
                _txPr = value;
                notifyPropertyChanged("TextProperties");
            }
        }


        public Surface Floor
        {
            get { return _floor; }
            set
            {
                _floor = value;
                notifyPropertyChanged("Floor");
            }
        }

        public Surface SideWall
        {
            get { return _sideWall; }
            set
            {
                _sideWall = value;
                notifyPropertyChanged("SideWall");
            }
        }

        public Surface BackWall
        {
            get { return _backWall; }
            set
            {
                _backWall = value;
                notifyPropertyChanged("BackWall");
            }
        }


        public Legend Legend
        {
            get { return _legend; }
            set
            {
                _legend = value;
                notifyPropertyChanged("Legend");
            }
        }


        public PlotArea PlotArea
        {
            get
            {
                if (_plotArea == null)
                    _plotArea = new PlotArea();
                return _plotArea;
            }
            set
            {
                _plotArea = value;
                notifyPropertyChanged("PlotArea");
            }
        }


        public View3D View3D
        {
            get
            {
                if (_view3D == null)
                {
                    foreach (ChartBase chart in PlotArea.Charts)
                    {
                        if (chart is I3DChart)
                            _view3D = new View3D();
                    }
                }
                return _view3D;
            }
            set
            {
                _view3D = value;
                notifyPropertyChanged("View3D");
            }
        }


        public Protection Protection
        {
            get { return _protection; }
            set
            {
                _protection = value;
                notifyPropertyChanged("Protection");
            }
        }


        public ExtensionElement Extension
        {
            get { return _extension; }
            set
            {
                _extension = value;
                notifyPropertyChanged("Extension");
            }
        }


        public List<DrawingAnchor> UserShapes
        {
            get { return _userShapes; }
        }

        public bool DataLabelsOverMaximum
        {
            get { return _showDLblsOverMax; }
            set
            {
                _showDLblsOverMax = value;
                notifyPropertyChanged("DataLabelsOverMaximum");
            }
        }

        public bool RoundedCorners
        {
            get { return _roundedCorners; }
            set
            {
                _roundedCorners = value;
                notifyPropertyChanged("RoundedCorners");
            }
        }


        public string Language
        {
            get { return _lang; }
            set
            {
                _lang = value;
                notifyPropertyChanged("Language");
            }
        }


        public ChartStyle Style
        {
            get { return _chartStyle; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                _chartStyle = value;
                notifyPropertyChanged("Style");
            }
        }


        public bool AutoTitleDeleted
        {
            get { return _autoTitleDeleted; }
            set { _autoTitleDeleted = value; }
        }

        /*
        public Brush Background
        {
            get
            {
                if (this.ShapeProperties == null)
                    return ShapeProperties.DefaultFill;
                return this.ShapeProperties.Fill;
            }
        }
        */

        public bool PlotVisibleOnly
        {
            get { return _plotVisOnly; }
            set { _plotVisOnly = value; }
        }

        public DisplayBlanksAs DisplayBlanksAs
        {
            get { return _dispBlanksAs; }
            set
            {
                _dispBlanksAs = value;
                notifyPropertyChanged("DisplayBlanksAs");
            }
        }

        public ColorMapping ColorMapOverride
        {
            get { return _clrMapOvr; }
            set
            {
                _clrMapOvr = value;
                notifyPropertyChanged("ColorMapOverride");
            }
        }



        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (var c = context.Read("chartSpace"))
            {

                {
                    _date1904 = c.ReadOptionalElementBooleanAttribute("date1904", false);
                    Language = c.ReadOptionalElementStringAttribute("lang", "val");
                    RoundedCorners = c.ReadOptionalElementBooleanAttribute("roundedCorners", false); //\\not documented?
                    var s = c.ReadOptionalElement<ChartStyle>("style");
                    if (s != null)
                        Style = s;
                    ColorMapOverride = c.ReadOptionalElementAs<ColorMapping>("clrMapOvr");
                    _pivotSource = c.ReadOptionalElement<PivotSource>("pivotSource");
                    Protection = c.ReadOptionalElement<Protection>("protection");
                    using (ReadContext ccc = c.Read("chart"))
                    {
                        Title = ccc.ReadOptionalElement<Title>("title");
                        _autoTitleDeleted =
                            ccc.ReadOptionalElementBooleanAttribute("autoTitleDeleted", "val", false, true);
                        _pivotFormats.Clear();
                        _pivotFormats.AddRange(c.ReadElements<PivotFormat>("pivotFmts", "pivotFmt"));

                        View3D = ccc.ReadOptionalElement<View3D>("view3D");
                        Floor = ccc.ReadOptionalElementAs<Surface>("floor");
                        SideWall = ccc.ReadOptionalElementAs<Surface>("sideWall");
                        BackWall = ccc.ReadOptionalElementAs<Surface>("backWall");
                        PlotArea = ccc.ReadOptionalElement<PlotArea>("plotArea");
                        Legend = ccc.ReadOptionalElement("legend", () => new Legend(this));
                        _plotVisOnly = ccc.ReadOptionalElementBooleanAttribute("plotVisOnly", false, false);
                        DisplayBlanksAs =
                            ccc.ReadOptionalElementEnumAttribute("dispBlanksAs", "val",
                                                                 DisplayBlanksAs.Zero,
                                                                 DisplayBlanksAs.Zero);
                        _showDLblsOverMax = ccc.ReadOptionalElementBooleanAttribute("showDLblsOverMax", false);
                        ccc.WarnIf("crtExt");
                    }
                    //\\ c = new ReadContext(reader, part, ChartConstants.ChartNamespace);
                    ShapeProperties = c.ReadOptionalElement<ShapeProperties>("spPr");
                    TextProperties = c.ReadOptionalElementAs<TextBody>("txPr");
                    this.externalData = c.ReadOptionalElement<ExternalData>("externalData");
                    PrintSettings = c.ReadOptionalElement<PrintSettings>("printSettings");
                    if (c.ReaderLocalName == "userShapes")
                    {
                        using (ReadContext c2 = c.Read("userShapes"))
                        {
                            string id = c2.GetString(OfficeConstants.RelationshipNamespace + "id");
                            PackageRelationship rel = context.Part.GetRelationship(id);
                            using (ReadContext c3 = c2.OpenRelatedContext(rel, ChartConstants.ChartNamespaceUri))
                            {
                                using (ReadContext uc = c3.Read("userShapes"))
                                {
                                    DrawingAnchor a = DrawingAnchor.ReadAnchor(uc);
                                    while (a != null)
                                    {
                                        UserShapes.Add(a);
                                        a = DrawingAnchor.ReadAnchor(uc);
                                    }
                                }
                            }
                        }
                    }
                    Extension = c.ReadOptionalElement<ExtensionElement>("extLst");
                }
            }
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            using (WriteContext c = context.Write("chartSpace"))
            {
                c.DeclareNamespace(DrawingConstants.DrawingNamespace);
                {
                    c.WriteOptionalElementBooleanAttribute("date1904", Date1904, false);
                    c.WriteOptionalElementStringAttribute("lang", Language);
                    c.WriteOptionalElementBooleanAttribute("roundedCorners", RoundedCorners, false);
                    if (Style.Index != 2)
                        c.WriteOptionalElement(Style);

                    c.WriteOptionalElementAs(ColorMapOverride, "clrMapOvr");
                    c.WriteOptionalElement(_pivotSource);
                    c.WriteOptionalElement(Protection);
                    using (WriteContext ccc = c.Write("chart"))
                    {
                        ccc.WriteOptionalElement(Title);
                        ccc.WriteOptionalElementBooleanAttribute("autoTitleDeleted", AutoTitleDeleted, false);
                        if (_pivotFormats.Count > 0)
                        {
                            using (WriteContext c2 = c.Write("pivotFmts"))
                            {
                                c2.WriteElements(_pivotFormats);
                            }
                        }
                        ccc.WriteOptionalElement(View3D);
                        ccc.WriteOptionalElementAs(Floor, "floor");
                        ccc.WriteOptionalElementAs(SideWall, "sideWall");
                        ccc.WriteOptionalElementAs(BackWall, "backWall");

                        ccc.WriteOptionalElement(PlotArea);
                        ccc.WriteOptionalElement(Legend);
                        ccc.WriteOptionalElementBooleanAttribute("plotVisOnly", _plotVisOnly, false);
                        ccc.WriteOptionalElementEnumAttribute("dispBlanksAs", "val", DisplayBlanksAs,
                                                              DisplayBlanksAs.Zero,
                                                              DisplayBlanksAs.Zero);
                        ccc.WriteOptionalElementBooleanAttribute("showDLblsOverMax", _showDLblsOverMax, false);
                        //\\ default OK?
                        ccc.WarnIf("crtExt");
                    }
                    //\\ c = new ReadContext(reader, part, ChartConstants.ChartNamespace);
                    c.WriteOptionalElement(ShapeProperties);
                    c.WriteOptionalElementAs(TextProperties, "txPr");
                    c.WriteOptionalElement(externalData);
                    c.WriteOptionalElement(PrintSettings);
                    if (UserShapes != null && UserShapes.Count > 0)
                    {
                        using (
                            RelatedWriteContext relatedUserShapesContext =
                                c.CreateRelatedContext(ChartConstants.ChartNamespace,
                                                       c.GetAvailableUri(@"../drawings/drawing{0}.xml"),
                                                       ChartConstants.ChartUserShapesRelationshipType,
                                                       ChartConstants.ChartShapesContentType))
                        {
                            using (WriteContext c3 = relatedUserShapesContext.Write("userShapes"))
                            {
                                foreach (DrawingAnchor a in UserShapes)
                                    c3.WriteElement(a);
                            }
                            using (WriteContext c3 = c.Write("userShapes"))
                            {
                                c3.SetString(OfficeConstants.RelationshipNamespace + "id",
                                             relatedUserShapesContext.Relationship.Id);
                            }
                        }
                    }
                    c.WriteOptionalElement(Extension);
                }
            }
        }

        #endregion

        #region IShape Members

        public ShapeProperties ShapeProperties
        {
            get
            {
                if (_spPr == null)
                    _spPr = new ShapeProperties();
                return _spPr;
            }
            set
            {
                _spPr = value;
                notifyPropertyChanged("ShapeProperties");
            }
        }

        #endregion

      
    }
}